package com.kili.file.controller;

import com.kili.file.common.IConstants;
import com.kili.file.controller.request.FileUploadRequest;
import com.kili.file.controller.vo.BaseResponse;
import com.kili.file.enums.ResponseCode;
import com.kili.file.service.FileHandleService;
import com.kili.file.service.FileUploadService;
import com.kili.file.service.ImageUploadService;
import com.kili.file.config.elect.DynamicElect;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.WebAsyncTask;

import static com.kili.file.enums.PictureType.PICTURE_TYPE_LIST;
import static com.kili.file.utils.FileUtil.getFileSuffixName;

/**
 * @author Gordon
 * @version 2019/3/27
 */
@Slf4j
@RestController
@RequestMapping("/v1.0")
public class FileUploadController {

    private ThreadPoolTaskExecutor taskExecutor;

    private ImageUploadService imageUploadService;

    private FileHandleService fileHandleService;

    @PostMapping(value = "/fileUpload")
    public WebAsyncTask<BaseResponse<String>> fileUpload(@DynamicElect FileUploadService fileUploadService, FileUploadRequest request) {
        String fileName = request.getFile().getOriginalFilename();
        log.info("File upload request file name:{} other info:{}", fileName, request);
        // Async task for file upload
        WebAsyncTask<BaseResponse<String>> asyncTask =
                new WebAsyncTask<>(IConstants.TASK_TIME_OUT, taskExecutor, () -> {
                    String url;
                    if (PICTURE_TYPE_LIST.contains(getFileSuffixName(request.getFile().getOriginalFilename()))) {
                        url = imageUploadService.imageUploadHandler(request);
                    } else {
                        url = fileUploadService.uploadHandler(request);
                        fileHandleService.save(request);
                    }
                    return BaseResponse.of(url);
                });

        asyncTaskErrorProcess(request, asyncTask);
        return asyncTask;
    }

    private void asyncTaskErrorProcess(FileUploadRequest req, WebAsyncTask<BaseResponse<String>> asyncTask) {
        // if task has a error,it will execute the following
        asyncTask.onError(() -> {
            log.error("File upload error occurred - req:{}", req);
            return BaseResponse.of(ResponseCode.INTERNAL_ERROR);
        });

        // if task has time out,it will execute the following
        asyncTask.onTimeout(() -> {
            log.warn("File upload time out - req:{}", req);
            return BaseResponse.of(ResponseCode.INTERNAL_ERROR);
        });
    }
}
